﻿using System;
using GeoAPI.Geometries;

namespace NetTopologySuite.Algorithm
{
	public class RayCrossingCounter
	{
		public static Location LocatePointInRing(Coordinate p, Coordinate[] ring)
		{
			RayCrossingCounter rayCrossingCounter = new RayCrossingCounter(p);
			for (int i = 1; i < ring.Length; i++)
			{
				Coordinate p2 = ring[i];
				Coordinate p3 = ring[i - 1];
				rayCrossingCounter.CountSegment(p2, p3);
				if (rayCrossingCounter.IsOnSegment)
				{
					return rayCrossingCounter.Location;
				}
			}
			return rayCrossingCounter.Location;
		}

		public static Location LocatePointInRing(Coordinate p, ICoordinateSequence ring)
		{
			RayCrossingCounter rayCrossingCounter = new RayCrossingCounter(p);
			Coordinate coordinate = new Coordinate();
			Coordinate coordinate2 = new Coordinate();
			int count = ring.Count;
			for (int i = 1; i < count; i++)
			{
				ring.GetCoordinate(i, coordinate);
				ring.GetCoordinate(i - 1, coordinate2);
				rayCrossingCounter.CountSegment(coordinate, coordinate2);
				if (rayCrossingCounter.IsOnSegment)
				{
					return rayCrossingCounter.Location;
				}
			}
			return rayCrossingCounter.Location;
		}

		public RayCrossingCounter(Coordinate p)
		{
			this._p = p;
		}

		public void CountSegment(Coordinate p1, Coordinate p2)
		{
			if (p1.X < this._p.X && p2.X < this._p.X)
			{
				return;
			}
			if (this._p.X == p2.X && this._p.Y == p2.Y)
			{
				this._isPointOnSegment = true;
				return;
			}
			if (p1.Y == this._p.Y && p2.Y == this._p.Y)
			{
				double x = p1.X;
				double x2 = p2.X;
				if (x > x2)
				{
					x = p2.X;
					x2 = p1.X;
				}
				if (this._p.X >= x && this._p.X <= x2)
				{
					this._isPointOnSegment = true;
				}
				return;
			}
			if ((p1.Y > this._p.Y && p2.Y <= this._p.Y) || (p2.Y > this._p.Y && p1.Y <= this._p.Y))
			{
				double x3 = p1.X - this._p.X;
				double num = p1.Y - this._p.Y;
				double x4 = p2.X - this._p.X;
				double num2 = p2.Y - this._p.Y;
				double num3 = (double)RobustDeterminant.SignOfDet2x2(x3, num, x4, num2);
				if (num3 == 0.0)
				{
					this._isPointOnSegment = true;
					return;
				}
				if (num2 < num)
				{
					num3 = -num3;
				}
				if (num3 > 0.0)
				{
					this._crossingCount++;
				}
			}
		}

		public bool IsOnSegment
		{
			get
			{
				return this._isPointOnSegment;
			}
		}

		public Location Location
		{
			get
			{
				if (this._isPointOnSegment)
				{
					return Location.Boundary;
				}
				if (this._crossingCount % 2 == 1)
				{
					return Location.Interior;
				}
				return Location.Exterior;
			}
		}

		public bool IsPointInPolygon
		{
			get
			{
				return this.Location != Location.Exterior;
			}
		}

		private readonly Coordinate _p;

		private int _crossingCount;

		private bool _isPointOnSegment;
	}
}
